package parser

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"

	"gitee.com/u-language/u-language/ucom/ast"
	"gitee.com/u-language/u-language/ucom/errcode"
	"gitee.com/u-language/u-language/ucom/internal/errutil"
	"gitee.com/u-language/u-language/ucom/internal/utils"
	"gitee.com/u-language/u-language/ucom/ir2"
	"gitee.com/u-language/u-language/ucom/lex"
)

// ParserAuto2 根据path是目录还是文件决定调用 [ParserPackag2e] 或 [ParserFile2]
func ParserAuto2(path string, thread bool, errctx *errcode.ErrCtx) (ir2.Ir2, error) {
	fileinfo, err := os.Stat(path)
	if err != nil {
		return nil, err
	}
	if fileinfo.IsDir() { //如果是目录
		panic(errutil.NewErr2(errutil.CompileErr, "不支持"))
	}
	if filepath.Ext(path) == "" { //如果文件没有扩展名
		return nil, FileNoExt
	}
	return ParserFile2(path, errctx, true, thread)
}

// openfileAndSize 同时获取文件描述符和文件大小
func openfileAndSize(path string) (*os.File, int64, error) {
	// 打开文件
	file, err := os.Open(path)
	if err != nil {
		return nil, 0, err
	}
	Info, err := file.Stat()
	if err != nil {
		return nil, 0, err
	}
	return file, Info.Size(), err
}

// ParserFile2 从一个代码文件创建 [ir2.File] 的指针
//   - path是文件路径
//   - errctx是错误处理上下文
//   - IsCheck是控制是否进行语义检查
//   - Thread是控制是否并发
func ParserFile2(path string, errctx *errcode.ErrCtx, IsCheck bool, Thread bool) (*ir2.File, error) {
	file, size, err := openfileAndSize(path) //获取文件描述符，文件大小
	if err != nil {
		return nil, err
	}
	var r *bufio.Reader = bufio.NewReaderSize(file, int(size))
	Filestr, err := utils.ReadAllLine(r) //读取文件所有内容并分行
	if err != nil {
		return nil, err
	}
	//var t time.Time
	FT := lex.Lex(path, Filestr, errctx, false) //进行词法分析
	try_print_FT(FT)
	if errctx.Errbol() { //如果词法分析有错误·
		return nil, errutil.NewErr2("错误", "词法分析有错")
	}
	importTable := make(map[string]*ast.Package)
	tree := ast.NewTree(FT, errctx, ast.NewSbt(Thread), &importTable) //创建抽象语法树
	if errctx.Errbol() {                                              //代码有错误
		return nil, errutil.NewErr2("1", "1")
	}
	try_print(tree)
	err = loadAllImport(filepath.Dir(path), tree.ImportTable, tree.ImportPackage, tree.ImportLoacl, Thread, errctx, tree.Sbt)
	if err != nil {
		return nil, err
	}
	irfile := ir2.NewFile(tree, errctx)
	if Debug {
		fmt.Println(irfile)
	}
	// if IsCheck { //如果要进行语义检查
	// 	try_new_print_check(&t)
	// 	check2.CheckFile(irfile)
	// 	if Debug == "true" {
	// 		fmt.Println(irfile)
	// 	}
	// 	try_Print_Time(&t)
	// }
	return irfile, nil
}
